package com.tjbaobao.videoplayol.ui;

import android.content.Context;
import android.hardware.Camera;
import android.media.AudioManager;
import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.widget.RelativeLayout;

import com.tjbaobao.framework.utils.BaseHandler;
import com.tjbaobao.framework.utils.BaseTimerTask;
import com.tjbaobao.framework.utils.DeviceUtil;
import com.tjbaobao.framework.utils.Tools;
import com.tjbaobao.videoplayol.impl.VideoRecordImpl;
import com.tjbaobao.videoplayol.listener.OnVideoRecordListener;

import java.io.File;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 视频录像器
 * Created by TJbaobao on 2018/1/17.
 */

@SuppressWarnings("unused")
public class VideoRecordView extends BaseSurfaceView implements VideoRecordImpl,MediaRecorder.OnErrorListener{
    public VideoRecordView(Context context) {
        super(context);
    }

    public VideoRecordView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public VideoRecordView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public static final int CAMERA_TYPE_BACK =  Camera.CameraInfo.CAMERA_FACING_BACK ;
    public static final int CAMERA_TYPE_FRONT = Camera.CameraInfo.CAMERA_FACING_FRONT;
    public static final int SCREEN_TYPE_VERTIAL = 1;
    public static final int SCREEN_TYPE_HORIZONTAL= 0;

    private static final int HANDLER_WHAT_UPDATE_TIME = 101;

    private SurfaceHolder mSurfaceHolder ;
    private Camera mCamera ;
    private int cameraType = CAMERA_TYPE_BACK ;//前后摄像头
    private int screenType = SCREEN_TYPE_HORIZONTAL ;//屏幕方向
    private boolean isError ;
    private boolean isStart = false;

    private static final int maxDuration = 10*60*1000*10;
    private int videoWidth,videoHeight ;
    private long videoTime ;

    private MediaRecorder mMediaRecorder = new MediaRecorder();

    @Override
    protected void onInitView(Context context, AttributeSet attrs, int defStyleAttr) {
        mSurfaceHolder = this.getHolder();
        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        mSurfaceHolder.addCallback(new CustomCallBack());
        wakeLock();
        mTimerTask = new MyTimerTask();
    }

    @Override
    public boolean start(String path) {
        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        if(audioManager!=null)
        {
            audioManager.setStreamMute(AudioManager.STREAM_SYSTEM, true);
        }
        File videoFile = new File(path);
        mMediaRecorder.reset();
        initCamera(cameraType);
        if (mCamera != null)
            mMediaRecorder.setCamera(mCamera);
        mMediaRecorder.setOnErrorListener(this); // 设置出错处理接口，拦截错误，设置后不会崩
        mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());//预览画面
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);// 视频源
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);// 音频源
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// 视频输出格式
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);// 音频格式
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// 视频录制格式
        mMediaRecorder.setVideoEncodingBitRate(85 * 1024 * 8*5);// 5M/min，设置比特率（每秒bit大小）
        mMediaRecorder.setVideoSize(videoWidth, videoHeight);// 设置分辨率：
        // recorder.setVideoFrameRate(15);// 设置帧频率,需要硬件支持
        if(screenType==SCREEN_TYPE_VERTIAL&&cameraType==CAMERA_TYPE_BACK)
            mMediaRecorder.setOrientationHint(90);// 输出旋转90度，保持竖屏录制
        else if(screenType==SCREEN_TYPE_VERTIAL&&cameraType==CAMERA_TYPE_FRONT)
            mMediaRecorder.setOrientationHint(270);// 输出旋转90度，保持竖屏录制
//        if(screenType==SCREEN_TYPE_HORIZONTAL)
//        {
//            mMediaRecorder.setOrientationHint(90);// 输出旋转90度
//        }
        mMediaRecorder.setMaxDuration(maxDuration);
        mMediaRecorder.setOutputFile(videoFile.getAbsolutePath());
        try {
            mMediaRecorder.prepare();
            mMediaRecorder.start();
            mTimerTask.startTimer(0,100);
            isStart = true;
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (RuntimeException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(!isStart)
            {
                Tools.showToast("启动相机失败，请重试");
            }
        }
        if(audioManager!=null)
        {
            audioManager.setStreamMute(AudioManager.STREAM_SYSTEM, false);
        }
        return isStart;
    }

    @Override
    public boolean stop() {
        if(!isStart)
        {
            return false;
        }
        boolean bState = false;
        try {
            if (mMediaRecorder != null) {
                mMediaRecorder.stop();
                mMediaRecorder.reset();
                mMediaRecorder = null;
            }
            freeCameraResource();
            bState = true;
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (RuntimeException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        mTimerTask.stopTimer();
        return bState;
    }

    @Override
    public int changeCamera()
    {
        if(cameraType==CAMERA_TYPE_BACK)
        {
            cameraType = CAMERA_TYPE_FRONT;
        }
        else
        {
            cameraType = CAMERA_TYPE_BACK;
        }
        initCamera(cameraType);
        return cameraType ;
    }

    @Override
    public int  changeScreen()
    {
        if(screenType==SCREEN_TYPE_HORIZONTAL)
        {
            screenType = SCREEN_TYPE_VERTIAL;
        }
        else
        {
            screenType = SCREEN_TYPE_HORIZONTAL;
        }
        freeCameraResource();
        return screenType;
    }


    @Override
    public void onDestroy() {
        freeCameraResource();
    }


    @Override
    public void onError(MediaRecorder mr, int what, int extra) {
        try {
            if (mr != null)
            {
                mr.reset();
            }
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public boolean isStart() {
        return isStart;
    }

    public int getVideoWidth() {
        return videoWidth;
    }

    public int getVideoHeight() {
        return videoHeight;
    }

    public long getVideoTime() {
        return videoTime;
    }

    //region==================内部方法======================

    /**
     * 初始化摄像头
     */
    private void initCamera(int cameraType)
    {
        if (mCamera != null) {
            freeCameraResource();
        }
        try {
            mCamera = Camera.open(cameraType);
            if (mCamera == null)
                return;
            Camera.Size size = setBestCameraResolution(mCamera.getParameters());
            videoWidth = size.width;
            videoHeight = size.height;
            setCameraParams();
            if(screenType==1)
                mCamera.setDisplayOrientation(90);
            mCamera.setPreviewDisplay(mSurfaceHolder);
            mCamera.startPreview();
            mCamera.unlock();
        } catch (Exception e) {
            e.printStackTrace();
            freeCameraResource();
            if(isError)
            {
                Tools.showToast("开启摄像头失败");
            }
            else
            {
                isError = true ;
                initCamera(cameraType);
            }
        }
    }

    /**
     * 释放摄像头资源
     */
    private void freeCameraResource()
    {
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.setPreviewCallback(null);
            mCamera.setPreviewCallbackWithBuffer(null);
            mCamera.lock();
            mCamera.release();
            mCamera = null;
        }
    }

    /**
     * 配置摄像头参数
     */
    private void setCameraParams() {
        if (mCamera != null) {
            Camera.Parameters params = mCamera.getParameters();
            if(cameraType!=Camera.CameraInfo.CAMERA_FACING_FRONT)
            {
                try {
                    if(!isError)
                    {
                        params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
                    }
                } catch (Exception e) {
                    isError = true;
                }
            }
            if(!isError)
            {
                Camera.Size size= getBestCameraResolution(params);
                int preWidth = size.width ;
                int preHeight = size.height;
                params.setPreviewSize(preWidth,preHeight);
                int screenWidth = DeviceUtil.getScreenWidth();
                int screenHeight = DeviceUtil.getScreenHeight();
                int nowWidth,nowHeight;
                if(screenType==1)
                {
                    nowWidth = screenWidth;
                    nowHeight = screenHeight*preWidth/preHeight;
                }
                else
                {
                    nowWidth = screenHeight*preWidth/preHeight;
                    nowHeight = screenHeight;
                }
                //修改显示区域大小
                RelativeLayout.LayoutParams rParams =(RelativeLayout.LayoutParams) this.getLayoutParams() ;
                if(rParams==null)
                {
                    rParams = new RelativeLayout.LayoutParams(nowWidth,nowHeight);
                }
                else
                {
                    rParams.width = nowWidth;
                    rParams.height = nowHeight ;
                }
                this.setLayoutParams(rParams);
            }
            mCamera.setParameters(params);
        }
    }

    /**
     * 设置最优的视频分辨率
     */
    private Camera.Size getBaseVideoResolution()
    {
        List<Camera.Size> sizes = getSupportedVideoSizes(mCamera);
        if (sizes != null) {
            for (Camera.Size size : sizes) {
                if (size.width == 640 && size.height == 480)
                {
                    return size ;
                }
                else if (size.width == 320 && size.height == 240)
                {
                    return size ;
                }
            }
        }
        return null;
    }

    /**
     * 获取最优的预览分辨率
     * @return Camera.Size ${@link Camera.Size}
     */
    @SuppressWarnings("UnusedAssignment")
    private Camera.Size getBaseResolutionRatio()
    {
        List<Camera.Size> sizeList = getSupportedVideoSizes(mCamera);
        sizeList.remove(sizeList.size()-1);
        int screenWidth = DeviceUtil.getScreenWidth();
        int screenHeight = DeviceUtil.getScreenHeight();

        int screenTemp = screenWidth;
        screenWidth = Math.max(screenWidth, screenHeight);
        screenHeight = Math.min(screenTemp,screenHeight);
        int i = 0 ;
        Camera.Size baseSize = null ;
        int bigSizeWidth = 0,bigSizeHeight=0 ;
        for(Camera.Size size :sizeList)
        {
            int width = size.width;
            int height = size.height;
            int nowWidth = screenHeight*width/height;
            int nowHeight = screenWidth*height/width ;
            if(i==0)
            {
                bigSizeWidth = nowWidth;
                bigSizeHeight = nowHeight ;
                baseSize = size ;
            }
            if(nowWidth<=screenWidth)
            {
                if(bigSizeWidth<=nowWidth)
                {
                    bigSizeWidth = nowWidth;
                    baseSize = size ;
                }
            }
            Tools.printLog("选择分辨率:width:"+width+",height="+height+",nowWidth="+nowWidth);
            i++;
        }
        return baseSize;
    }

    private Camera.Size setBestCameraResolution(Camera.Parameters parameters)
    {
        int screenWidth = DeviceUtil.getScreenWidth();
        int screenHeight = DeviceUtil.getScreenHeight();
        return getBestCameraResolution(parameters,screenWidth,screenHeight,false);
    }
    /**
     * 筛选最优显示分辨率
     * @param parameters ${@link Camera.Parameters}
     * @return ${@link Camera.Size}
     */
    @SuppressWarnings("SameParameterValue")
    private Camera.Size getBestCameraResolution(Camera.Parameters parameters, int bestWidth, int bestHeight, boolean smaill) {
        float tmp ;
        float mindiff = 100f;
        float baseRatio ;
        if (screenType == 0)
        {
            baseRatio = (float)bestWidth / (float)bestHeight;
        }
        else
        {
            baseRatio = (float)bestHeight / (float)bestWidth;

        }

        Camera.Size bestSize = null;
        List<Camera.Size> supportedPreviewSizes = parameters.getSupportedPreviewSizes();
        for (Camera.Size s : supportedPreviewSizes)
        {
            if(screenType==0)
            {
                int lastWidth = bestHeight*s.width/s.height;
                int lastHeight = bestWidth*s.height/s.width;
                if(lastWidth>DeviceUtil.getScreenWidth())
                {
                    continue ;
                }
            }
            else
            {
                int lastWidth = bestHeight*s.height/s.width;
                int lastHeight = bestWidth*s.width/s.height;
                if(lastHeight>DeviceUtil.getScreenHeight())
                {
                    continue ;
                }
            }
            float tmpRatio = (float) s.width / (float) s.height;
            tmp = Math.abs(tmpRatio - baseRatio);
            if (tmp <= mindiff) {
                if(bestSize==null)
                {
                    mindiff = tmp;
                    bestSize = s;
                }
                else
                {
                    if(smaill)
                    {
                        if(bestSize.width>s.width)
                        {
                            mindiff = tmp;
                            bestSize = s;
                        }
                    }
                    else
                    {
                        if(screenType==0)
                        {
                            if(Math.abs(bestSize.width-bestWidth)>Math.abs(s.width-bestWidth))
                            {
                                mindiff = tmp;
                                bestSize = s;
                            }
                        }
                        else
                        {
                            if(Math.abs(bestSize.height-bestWidth)>Math.abs(s.height-bestWidth))
                            {
                                mindiff = tmp;
                                bestSize = s;
                            }
                        }
                    }
                }

            }
        }
        return bestSize;
    }

    private Camera.Size getBestCameraResolution(Camera.Parameters parameters)
    {
        int screenWidth = DeviceUtil.getScreenWidth();
        int screenHeight = DeviceUtil.getScreenHeight();
        return getBestCameraResolution(parameters,screenWidth,screenHeight,false);
    }

    /**
     * 	获取摄像头所支持的分辨率列表
     * @param camera camera
     * @return Camera.Size
     */
    public List<Camera.Size> getSupportedVideoSizes(Camera camera) {
        List<Camera.Size> sizeList ;
        if(camera!=null)
        {
            if (camera.getParameters().getSupportedVideoSizes() != null) {
                sizeList =  camera.getParameters().getSupportedVideoSizes();
            } else {
                sizeList = camera.getParameters().getSupportedPreviewSizes();
            }
            Collections.sort(sizeList, new CameraSizeComparator());
            return sizeList;
        }
        return null;
    }

    /**
     * 排序工具类
     * @author Tjbaobao
     * @time 2016年12月1日 下午2:02:55
     */
    public  class CameraSizeComparator implements Comparator<Camera.Size> {
        //按升序排列
        public int compare(Camera.Size lhs, Camera.Size rhs) {
            if(lhs.width == rhs.width){
                return 0;
            }
            else if(lhs.width > rhs.width){
                return 1;
            }
            else{
                return -1;
            }
        }

    }

    /**
     * 保持屏幕常亮
     */
    private void wakeLock()
    {
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        if(pm!=null)
        {
            PowerManager.WakeLock mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
            mWakeLock.acquire(10*60*1000L /*10 minutes*/);
            mWakeLock.release();
        }
    }


    //endregion

    private class CustomCallBack implements SurfaceHolder.Callback
    {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            initCamera(cameraType);
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            freeCameraResource();
        }
    }

    private MyTimerTask mTimerTask ;
    private class MyTimerTask extends BaseTimerTask
    {
        long time = 0;
        @Override
        public void run() {
            time+=100;
            videoTime = time ;
            mHandler.sendMessage(HANDLER_WHAT_UPDATE_TIME,time);
        }
    }

    private BaseHandler mHandler = new BaseHandler();
    private class CallBack implements Handler.Callback
    {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what)
            {
                case HANDLER_WHAT_UPDATE_TIME:
                    long time = (long) msg.obj;
                    Tools.printLog(time+"");
                    if(mOnVideoRecordListener!=null)
                    {
                        mOnVideoRecordListener.onTime(time);
                    }
                    break;
            }
            return false;
        }
    }

    private OnVideoRecordListener mOnVideoRecordListener ;

    public OnVideoRecordListener getOnVideoRecordListener() {
        return mOnVideoRecordListener;
    }

    public void setOnVideoRecordListener(OnVideoRecordListener onVideoRecordListener) {
        mOnVideoRecordListener = onVideoRecordListener;
    }


    public void setScreenType(int screenType)
    {
        this.screenType = screenType;
    }

    public void setCameraType(int cameraType)
    {
        this.cameraType = cameraType ;
    }

}
